package kz.pompei.ifacer.testers;

import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;

import kz.pompei.ifacer.cursor_manager.def.DefCursorManager;
import kz.pompei.ifacer.grot.GrotPanel;
import kz.pompei.ifacer.grot.acts.ActContainer;
import kz.pompei.ifacer.grot.acts.AddAct;
import kz.pompei.ifacer.model.widgets.Widget;
import kz.pompei.ifacer.model.widgets.WidgetButton;
import kz.pompei.ifacer.model.widgets.WidgetCheck;
import kz.pompei.ifacer.model.widgets.WidgetForm;
import kz.pompei.ifacer.model.widgets.WidgetGrid;
import kz.pompei.ifacer.model.widgets.WidgetLabel;
import kz.pompei.ifacer.visio.def.DefVisio;

public class GrotPanelTester {
  public static void main(String[] args) throws Exception {
    new GrotPanelTester().run();
  }
  
  private void run() throws Exception {
    JFrame frame = new JFrame();
    frame.setTitle("Построение логики грота");
    frame.setBounds(100, 100, 1600, 600);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    final GrotPanel pane = createPanel();
    frame.setContentPane(pane);
    
    fillMenuBar(frame, pane);
    fillShortKeys(frame, pane);
    
    frame.setVisible(true);
  }
  
  private void fillShortKeys(JFrame frame, final GrotPanel grot) {
    frame.addKeyListener(new KeyAdapter() {
      
      @Override
      public void keyReleased(KeyEvent e) {
        try {
          keyReleasedInner(e);
        } catch (Exception e1) {
          throw new RuntimeException(e1);
        }
      }
      
      private void keyReleasedInner(KeyEvent e) throws Exception {
        if (e.isControlDown()) {
          //Ctrl ...................
          if (e.getKeyCode() == KeyEvent.VK_Z) {
            if (e.isShiftDown()) {
              grot.redo();//Ctrl+Shift+Z
            } else {
              grot.undo();//Ctrl+Z
            }
          }
          if (!e.isShiftDown() && e.getKeyCode() == KeyEvent.VK_A) {
            grot.selectAll();//Ctrl+A
          }
          if (!e.isShiftDown() && e.getKeyCode() == KeyEvent.VK_I) {
            exportImage(grot);//Ctrl+I
          }
          if (!e.isShiftDown() && e.getKeyCode() == KeyEvent.VK_O) {
            open(grot);//Ctrl+O
          }
          if (e.getKeyCode() == KeyEvent.VK_S) {
            save(e.isShiftDown(), grot);//Ctrl+(Shift+)S
          }
        } else {
          //No Ctrl ...........
          if (!e.isShiftDown() && e.getKeyCode() == KeyEvent.VK_ESCAPE) {
            grot.clearSelection();//Esc
          }
          if (!e.isShiftDown() && e.getKeyCode() == KeyEvent.VK_DELETE) {
            grot.deleteSelected();//Delete
          }
        }
      }
    });
  }
  
  private void exportImage(GrotPanel grot) throws Exception {
    JFileChooser fc = new JFileChooser();
    fc.setFileFilter(new FileFilter() {
      @Override
      public String getDescription() {
        return "png files";
      }
      
      @Override
      public boolean accept(File f) {
        if (f.isDirectory()) return true;
        return f.getAbsolutePath().endsWith(".png");
      }
    });
    if (JFileChooser.APPROVE_OPTION != fc.showSaveDialog(null)) return;
    File file = fc.getSelectedFile();
    
    if (!file.getAbsolutePath().endsWith(".png")) {
      file = new File(file.getAbsolutePath() + ".png");
    }
    
    BufferedImage im = grot.getExportImage();
    
    ImageIO.write(im, "png", file);
  }
  
  private void fillMenuBar(JFrame frame, final GrotPanel grot) {
    MenuBar mb = new MenuBar();
    frame.setMenuBar(mb);
    {
      Menu actionMenu = new Menu("Компоненты");
      mb.add(actionMenu);
      
      class Asd {
        String menuCaption;
        Widget widget;
        
        public Asd(String menuCaption, Widget widget) {
          this.menuCaption = menuCaption;
          this.widget = widget;
        }
      }
      
      final List<Asd> list = new ArrayList<>();
      list.add(new Asd("Добавить форму", new WidgetForm()));
      list.add(new Asd("Добавить метку", new WidgetLabel()));
      list.add(new Asd("Добавить кнопку", new WidgetButton()));
      list.add(new Asd("Добавить грид", new WidgetGrid()));
      list.add(new Asd("Добавить чек-бокс", new WidgetCheck()));
      
      for (final Asd asd : list) {
        MenuItem mi = new MenuItem(asd.menuCaption);
        actionMenu.add(mi);
        mi.addActionListener(new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            grot.addWidget(asd.widget.copy().resetUuid());
          }
        });
      }
    }
    {
      Menu actionMenu = new Menu("Действия");
      mb.add(actionMenu);
      
      {
        MenuItem mi = new MenuItem("Откат");
        actionMenu.add(mi);
        mi.addActionListener(new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            try {
              grot.actContainer.undo();
              grot.repaint(100);
            } catch (Exception e1) {
              throw new RuntimeException(e1);
            }
          }
        });
      }
      {
        MenuItem mi = new MenuItem("Возобновить");
        actionMenu.add(mi);
        mi.addActionListener(new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            try {
              grot.actContainer.redo();
              grot.repaint(100);
            } catch (Exception e1) {
              throw new RuntimeException(e1);
            }
          }
        });
      }
    }
  }
  
  private GrotPanel createPanel() throws Exception {
    ActContainer acts = new ActContainer();
    
    {
      WidgetForm w = new WidgetForm();
      acts.addAct(new AddAct(w));
    }
    {
      WidgetLabel w = new WidgetLabel();
      w.x = 120;
      acts.addAct(new AddAct(w));
    }
    {
      WidgetLabel w = new WidgetLabel();
      w.x = 120;
      w.y += 100;
      w.text = "Привет весь мир!!!";
      acts.addAct(new AddAct(w));
    }
    return new GrotPanel(acts, new DefVisio(), new DefCursorManager());
  }
  
  private void save(boolean saveAs, GrotPanel grot) throws Exception {
    if (grot.workingFile == null || saveAs) {
      if (!changeWorkingFile(grot)) return;
      if (grot.workingFile == null) return;
      if (grot.workingFile.exists()) {
        if (JOptionPane.YES_OPTION != JOptionPane.showConfirmDialog(grot,
            "Вы действительно хотите заменить файл " + grot.workingFile + " на новый?",
            "Опасность потери данных", JOptionPane.YES_NO_OPTION)) return;
      }
    }
    if (grot.workingFile == null) return;
    
    FileOutputStream out = new FileOutputStream(grot.workingFile);
    grot.save(out);
    out.close();
  }
  
  private void open(GrotPanel grot) throws Exception {
    JFileChooser fc = new JFileChooser();
    fc.setFileFilter(new FileFilter() {
      @Override
      public String getDescription() {
        return ".iface.xml files";
      }
      
      @Override
      public boolean accept(File f) {
        if (f.isDirectory()) return true;
        return f.getAbsolutePath().endsWith(".iface.xml");
      }
    });
    if (JFileChooser.APPROVE_OPTION != fc.showOpenDialog(grot)) return;
    FileInputStream inStream = new FileInputStream(fc.getSelectedFile());
    grot.load(inStream);
    inStream.close();
    grot.workingFile = fc.getSelectedFile();
  }
  
  private boolean changeWorkingFile(GrotPanel grot) {
    JFileChooser fc = new JFileChooser();
    fc.setFileFilter(new FileFilter() {
      @Override
      public String getDescription() {
        return ".iface.xml files";
      }
      
      @Override
      public boolean accept(File f) {
        if (f.isDirectory()) return true;
        return f.getAbsolutePath().endsWith(".iface.xml");
      }
    });
    if (JFileChooser.APPROVE_OPTION != fc.showSaveDialog(null)) return false;
    File file = fc.getSelectedFile();
    
    if (!file.getAbsolutePath().endsWith(".iface.xml")) {
      file = new File(file.getAbsolutePath() + ".iface.xml");
    }
    
    grot.workingFile = file;
    return true;
  }
}
